package pro.jiug.files.controller;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FileUtils;
import org.apache.tomcat.jni.FileInfo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.servlet.ModelAndView;
import pro.jiug.files.model.FileModel;
import pro.jiug.files.model.User;
import pro.jiug.files.service.FilesService;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.net.URLDecoder;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Controller
@RequestMapping("/file")
public class FileController {

    //文件在系统地址
    @Value("${jiug.system.file-path}")
    private String sysFilePath;
    //文件在项目地址
    @Value("${jiug.project.file-path}")
    private String proFilePath;

    @Autowired
    private FilesService filesService;

    /*
        查询所有
     */
    @RequestMapping("/showALL")
    public ModelAndView showALL(ModelAndView modelAndView) {
        //返回files集合
        List<FileModel> filesList = filesService.selectFilesList(new FileModel());
        //前端传递数据
        modelAndView.addObject("fileList",filesList);
        modelAndView.setViewName("file");
        return modelAndView;
    }

    /*
        上传请求
            1、将文件信息存库
            2、将文件上传到服务器硬盘
     */
    @PostMapping("/upload")
    public String upload(@RequestParam("file") MultipartFile[] multipartFiles) throws Exception {
        for (MultipartFile multipartFile : multipartFiles) {
            //---数据获取
            //原文件名字
            String originalFilename = multipartFile.getOriginalFilename();
            //文件类型
            String contentType = multipartFile.getContentType();
            //获取文件后缀名
            String[] split = contentType.split("/");
            String fileExt = "." + split[1];
            //文件MD5码
            String fileMD5= DigestUtils.md5Hex(multipartFile.getInputStream());
            //文件大小
            long size = multipartFile.getSize();
            //是否是图片
            int isImg=0;
            if (multipartFile.getContentType().indexOf("image") != -1) {
                isImg=1;
            }
            //获取文件输入流
            InputStream fileInputStream=multipartFile.getInputStream();

            //---数据封装
            FileModel fileModel=new FileModel();
            fileModel.setName(originalFilename);
            fileModel.setExt(fileExt);
            fileModel.setMd5(fileMD5);
            fileModel.setSize(size);
            fileModel.setType(contentType);
            fileModel.setIsimg(isImg);
            fileModel.setUploadTime(new Date());
            //---数据处理
            filesService.insertFiles(fileModel);//存库

            saveFile(fileInputStream,fileMD5,fileExt);

        }

        return "redirect:/file/showALL";

    }

    @RequestMapping("/publish")
    public String publish(Integer id) throws Exception {
        if(id==null){//一键发布
            File rootFile=new File(sysFilePath);//构建原文件夹对象

            File[] files=rootFile.listFiles();
            for (int i = 0; i <files.length ; i++) {
                try {
                    InputStream fileInputStream=new FileInputStream(files[i]);
                    String fileName=files[i].getName();
                    String copyPath=getUploadPath();
                    File copyFile=new File(copyPath + File.separator + fileName);
                    OutputStream fileOutputStream=new FileOutputStream(copyFile);
                    byte[] b=new byte[1024];
                    int code;
                    code = fileInputStream.read(b);
                    while(code!=-1){
                        fileOutputStream.write(b, 0, code);
                        code=fileInputStream.read(b);
                    }
                    fileOutputStream.flush();
                } catch (FileNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

        }


        return "redirect:/file/showALL";

    }

    /**
     * 获取当前系统路径
     */
    private String getUploadPath() {
        File path = null;
        try {
            path = new File(ResourceUtils.getURL("classpath:").getPath());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        if (!path.exists()) path = new File("");
        File upload = new File(path.getAbsolutePath(), proFilePath);
        if (!upload.exists()) upload.mkdirs();
        return upload.getAbsolutePath();
    }

    /**
     * 将 文件流 ，存入服务器硬盘
     */
    private void saveFile(InputStream fileInputStream,String MD5,String ext) throws IOException {

        String filename = MD5+ext;

        OutputStream fileOutputStream=new FileOutputStream( sysFilePath + "/"+ filename);

        byte[] buffer =new byte[1024*1024];
        int bytesum = 0;
        int byteread = 0;
        while ((byteread=fileInputStream.read(buffer))!=-1)
        {
            bytesum+=byteread;
            fileOutputStream.write(buffer,0,byteread);
            fileOutputStream.flush();
        }
        fileOutputStream.close();
        fileInputStream.close();
    }


    //复制到特定目录下
    public void copyFiles(File rootFile,File copyFile){
        //如果目标目录是一个文件,则抛出不可复制到文件的异常
        if(copyFile.isFile()){
            throw new RuntimeException("不能将一个文件夹复制到一个文件当中");
        }
        //因为是复制所以，要保证复制后的文件夹和原文件夹的名字包括里面的子文件夹，子文件名字都保持一致
        String rootPath=rootFile.getAbsolutePath().substring(rootFile.getAbsolutePath().lastIndexOf('\\'));
        String fileName=rootFile.getName();//获取文件名
        //因此，新文件创建的时候，直接截取原文件的路径获取文件名字整合到目标文件夹的后面形成目标文件的路径
        String path=copyFile.getAbsolutePath()+rootPath;
        copyFile=new File(path);
        //如果复制的当前元素是文件，用流操作进行复制
        if(rootFile.isFile()){
            try {
                FileInputStream fis=new FileInputStream(rootFile);
                FileOutputStream fos=new FileOutputStream(copyFile);
                byte[] b=new byte[1024];
                int code;
                code = fis.read(b);
                while(code!=-1){
                    fos.write(b, 0, code);
                    code=fis.read(b);
                }
                fos.flush();
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }else{//如果当前file对象指代的是文件夹，那么直接创建一个空文件夹即可
            copyFile.mkdir();
            File[] files=rootFile.listFiles();
            //如果文件夹下面再有子元素，则递归循环复制
            if(files.length!=0){
                for(File f:files){
                    this.copyFiles(f, copyFile);
                }

            }

        }
    }

    public static void dirCopy(String srcPath, String destPath) {
        File src = new File(srcPath);
        if (!new File(destPath).exists()) {
            new File(destPath).mkdirs();
        }
        for (File s : src.listFiles()) {
            if (s.isFile()) {
                fileCopy(s.getPath(), destPath + File.separator + s.getName());
            } else {
                dirCopy(s.getPath(), destPath + File.separator + s.getName());
            }
        }
    }

    public static void fileCopy(String srcPath, String destPath) {
        File src = new File(srcPath);
        File dest = new File(destPath);
        //使用jdk1.7 try-with-resource 释放资源，并添加了缓存流
        try(InputStream is = new BufferedInputStream(new FileInputStream(src));
            OutputStream out =new BufferedOutputStream(new FileOutputStream(dest))) {
            byte[] flush = new byte[1024];
            int len = -1;
            while ((len = is.read(flush)) != -1) {
                out.write(flush, 0, len);
            }
            out.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /*
        文件下载
     */
//    @RequestMapping("/dowload")
//    public void dowload(HttpServletResponse response, int id) throws IOException {
//        Files files = filesService.queryById(id);
//        String Path = ResourceUtils.getURL("classpath:").getPath() + "/static" + files.getPath();
//        FileInputStream in = new FileInputStream(new File(URLDecoder.decode(Path), files.getNewfilename()));
//        response.setHeader("Content-Disposition", "attachment;filename=" + URLDecoder.decode(files.getOldfilename(), "UTF-8"));
//        ServletOutputStream os = response.getOutputStream();
//        IOUtils.copy(in, os);
//        IOUtils.closeQuietly(in);
//        IOUtils.closeQuietly(os);
//        files.setDowncounts(files.getDowncounts() + 1);
//        filesService.update(files);
//    }


    //删除功能
//    @RequestMapping("/delete")
//    public String delete(@RequestParam("id") int id,
//                         Model model) throws Exception {
//        Files files = filesService.queryById(id);
//        String path = ResourceUtils.getURL("classpath:").getPath() + "static" + files.getPath() + "/" + files.getNewfilename();
//        String decode = URLDecoder.decode(path);
//        File file = new File(decode);
//        boolean delete = file.delete();
//        if (delete) {
//            boolean b = filesService.deleteById(id);
//            if (b){
//                model.addAttribute("msg", "删除成功");
//                return "forward:/file/showALL";
//            }
//        }
//        model.addAttribute("msg", "删除失败");
//        return "forward:/file/showALL";
//    }


}
